package flex.cc.fenfa.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import flex.cc.PublicUtil;
import org.springframework.stereotype.Service;

import flex.cc.basicinformation.entity.ChannelEntity;
import flex.cc.basicinformation.entity.ServiceProviderEntity;
import flex.cc.basicinformation.service.ChannelService;
import flex.cc.basicinformation.service.ServiceProviderService;
import flex.cc.fenfa.dto.RuleCountEntity;
import flex.cc.fenfa.dto.RuleMainEntity;
import flex.cc.fenfa.dto.RuleServicerEntity;
import flex.cc.fenfa.dto.ServicerCountEntity;
import flex.cc.fenfa.service.RuleCountService;
import flex.cc.fenfa.service.RuleMainService;
import flex.cc.fenfa.service.RuleServicerService;
import flex.cc.fenfa.service.ServicerCountService;

/**
*
* @author WANGCONG
* 2021年10月17日下午5:28:18
* @desc 分发规则计算
*/
@Service
public class FenFaUtil {

	@Resource
    private RuleMainService ruleMainService;
	@Resource
    private RuleServicerService servicerService;
	@Resource
	private RuleCountService ruleCountService;
	@Resource
	private ServiceProviderService providerService;
	@Resource
	private ServicerCountService servicerCountService;
	@Resource
	private ChannelService channelService;
	/**
	*
	* @author WANGCONG
	* 2021年10月17日下午5:32:57
	* @desc 自动下单，根据渠道方、省市区、类型顺序匹配分发规则
	*/
	/**
	 * 
	 * resultMap.put("code", "01");  //01：规则匹配到的；02：服务商信息匹配到的；03：未匹配到
	 * resultMap.put("servicerId", "服务商Id");
	 */
	public Map<String, String> initChoiceServicerId(Map<String, String> paramMap) {
		Map<String, String> resultMap = new HashMap<>();
		Map<String, Object> paramsMap = new HashMap<>();
//		String channelId = paramMap.get("channelId"); //合作方编码，用于区分渠道方
//		String province = paramMap.get("province");
//		String city = paramMap.get("city");
//		String area = paramMap.get("area");
		
//		paramsMap.put("channelId", "34");
//      String s = "FSG001,FSG003,FSG005";
//      List<String> list = Arrays.asList(s.split(","));
//      paramsMap.put("serviceItem", list);
//      paramsMap.put("province", "河北省");
//      paramsMap.put("city", "石家庄市");
//      paramsMap.put("area", "裕华区");
		String clientId = paramMap.get("clientId");
		//根据clientId去查渠道商信息
		Map<String, String> channelMap = new HashMap<>();
		channelMap.put("clientId", clientId);
		List<ChannelEntity> channelList = channelService.findChannelByParam(channelMap);
		if(channelList.size()==0 || channelList==null){
			resultMap.put("code", "03");
			resultMap.put("msg", "clientId未匹配");
			return resultMap;
		}
		String channelId = channelList.get(0).getId().toString();
		// 2022-03-16 16:54:41【2.2-服务包配置需求】省市区及服务项目参数调用trim()，去掉空格，避免查询时因为有空格导致查不到数据
		String serviceItem = PublicUtil.isNotEmpty(paramMap.get("serviceItem")) ? paramMap.get("serviceItem").trim() : null;
		List<String> serviceItemList = PublicUtil.isNotEmpty(serviceItem) ? Arrays.asList(serviceItem.split(",")) : null;
		paramsMap.put("serviceItem", serviceItemList);
		paramsMap.put("channelId", channelId);
		paramsMap.put("province", PublicUtil.isNotEmpty(paramMap.get("province")) ? paramMap.get("province").trim() : null);
		paramsMap.put("city", PublicUtil.isNotEmpty(paramMap.get("city")) ? paramMap.get("city").trim() : null);
		paramsMap.put("area", PublicUtil.isNotEmpty(paramMap.get("area")) ? paramMap.get("area").trim() : null);
		RuleMainEntity ruleVo = ruleMainService.choiceServicer(paramsMap);
		paramsMap.put("status", "1"); // 2022-03-16 13:41:58【2.2-服务包配置需求】分发查询匹配的服务商，添加条件：服务商状态为1-启用
		if(ruleVo!=null){//有对应的匹配规则
//			resultMap = matchRule(ruleVo);
			resultMap = matchRule_v2(ruleVo, paramsMap);
			String code = resultMap.get("code");
			if("03".equals(code)){ //规则匹配不到，再轮询匹配服务商列表
				paramsMap.remove("dataIds");
				resultMap = matchServicer(paramsMap);
			}
		}else{//没有对应的匹配规则，去和服务商配置信息做匹配
			resultMap = matchServicer(paramsMap);
		}
		return resultMap;
	}

	/**
	*
	* @author WANGCONG
	* 2021年10月18日下午4:36:28
	* @desc 根据规则匹配
	*/
	public Map<String, String> matchRule(RuleMainEntity ruleVo) {
		Map<String, String> resultMap = new HashMap<>();
		String ruleId = ruleVo.getRuleId();
		resultMap.put("ruleId", ruleId);
		List<RuleServicerEntity> servicerList = servicerService.queryListByRuleId(ruleId);
		if(servicerList.size()==1){ //当前规则下只有一个服务商
			resultMap.put("code", "01");
			String servicerId = servicerList.get(0).getServiceId();
			resultMap.put("servicerId", servicerId);
			return resultMap;
		}else{ //当前规则下有多个服务商
			List<String> servicerIds = new ArrayList<String>();
			List<String> weights = new ArrayList<String>();
			Map<String,String> ratioMap = new HashMap<>(); //key-value：规则中配置的信息：服务商Id-权重比
			for(int i=0; i<servicerList.size(); i++){
				servicerIds.add(servicerList.get(i).getServiceId());
				weights.add(servicerList.get(i).getWeight());
				ratioMap.put(servicerList.get(i).getServiceId(), servicerList.get(i).getWeight());
			}
			Map<String, Object> countParams = new HashMap<>();
			countParams.put("ruleId", ruleId);
			countParams.put("servicerId", servicerIds);
			List<RuleCountEntity> ruleCountList = ruleCountService.checkCount(countParams);
			String selectServicerId = "";
			if(servicerList.size() > ruleCountList.size()){//今天分发的还没有全轮询到
				List<String> temp_servicerIds = new ArrayList<>(servicerIds);
				List<String> ruleServicerIds = ruleCountList.stream().map(e -> e.getServicerId()).collect(Collectors.toList());
				temp_servicerIds.removeAll(ruleServicerIds); //求差集，预先插入保存
				selectServicerId = temp_servicerIds.get(0);
				resultMap.put("code", "01");
				resultMap.put("servicerId", selectServicerId);
				return resultMap;
			}else{
				//到这里，说明规则中的服务商都已轮询下发过服务单，接下来根据权重去派发：ratioMap
				//ratioMap:系统配置占比；ruleCountMap:实际分发占比
				String newestServicerId = ""; //当前规则下，最近一次操作的服务商Id
				Date newestDate = null;
				int total = 0; //分发的总数，分母
				Map<String,String> ruleCountMap = new HashMap<>(); //key-value：规则统计中的数据：服务商Id-累计比
				for(int i=0; i<ruleCountList.size(); i++){
					RuleCountEntity entity = ruleCountList.get(i);
					total = entity.getCount();
					ruleCountMap.put(entity.getServicerId(), entity.getServerCount()*100/total+"");
					if(i==0){
						newestDate = entity.getCreateTime();
						newestServicerId = entity.getServicerId();
					}else{
						if(newestDate.before(entity.getCreateTime())){
							newestDate = entity.getCreateTime();
							newestServicerId = entity.getServicerId();
						}
					}
				}
				//拿到最新操作的服务商Id,以它下一个服务商Id元素为起点，遍历规则，遍历完，都超过权重比，则取第一个服务商
				//'5,3,2,1'字符串，以动态值'3'为分隔，重新排序为2,1,5,3
				List<String> sortList = sortServicerId(servicerIds, newestServicerId);
				String resultServicerId = "";
				for(int i=0; i<sortList.size(); i++){
					String servicerId = sortList.get(i);
					String xtRatio = ratioMap.get(servicerId); //系统配置的权重比
					String sjRatio = ruleCountMap.get(servicerId); //实际分发占比
					int result = xtRatio.compareTo(sjRatio); //1:大于；0:等于； -1:小于
					if(result>0){
						resultServicerId = servicerId;
						break;
					}
				}
				if(resultServicerId==""){ //表明实发占比不小于配置占比，默认取第一个服务商
					resultServicerId = servicerIds.get(0);
				}
				resultMap.put("code", "01");
				resultMap.put("servicerId", resultServicerId);
				return resultMap;
			}
		}
	}

	public Map<String, String> matchRule_v2(RuleMainEntity ruleVo, Map<String, Object> paramsMap) {
		Map<String, String> resultMap = new HashMap<>();
		String ruleId = ruleVo.getRuleId();
		resultMap.put("ruleId", ruleId);
		List<RuleServicerEntity> rule_servicerList = servicerService.queryListByRuleId(ruleId);
//		List<String> dataIds = rule_servicerList.stream().map(RuleServicerEntity::getDataId).collect(Collectors.toList());
		List<String> dataIds = rule_servicerList.stream().map(RuleServicerEntity::getServiceId).collect(Collectors.toList());
		paramsMap.put("dataIds", dataIds);
		List<ServiceProviderEntity> servicerList = providerService.choiceServicer(paramsMap);
		if(servicerList.size()==0){//没有
			resultMap.put("code", "03");
        	resultMap.put("msg", "没有匹配的服务商");
			return resultMap;
		}else if(servicerList.size()==1){ //当前规则下只有一个服务商
			resultMap.put("code", "01");
			String servicerId = servicerList.get(0).getId()+"";
			resultMap.put("servicerId", servicerId);
			return resultMap;
		}else{ //当前规则下有多个服务商
			Map<String, String> map = new HashMap<>();
			for(RuleServicerEntity r : rule_servicerList){
				map.put(r.getServiceId(), r.getWeight());
			}
			List<String> servicerIds = new ArrayList<String>();
			List<String> weights = new ArrayList<String>();
			Map<String,String> ratioMap = new HashMap<>(); //key-value：规则中配置的信息：服务商Id-权重比
			for(int i=0; i<servicerList.size(); i++){
				String tempServiceId = servicerList.get(i).getId()+"";
				servicerIds.add(tempServiceId);
				weights.add(map.get(tempServiceId));
				ratioMap.put(tempServiceId, map.get(tempServiceId));
			}
			Map<String, Object> countParams = new HashMap<>();
			countParams.put("ruleId", ruleId);
			countParams.put("servicerId", servicerIds);
			List<RuleCountEntity> ruleCountList = ruleCountService.checkCount(countParams);
			String selectServicerId = "";
			if(servicerList.size() > ruleCountList.size()){//今天分发的还没有全轮询到
				List<String> temp_servicerIds = new ArrayList<>(servicerIds);
				List<String> ruleServicerIds = ruleCountList.stream().map(e -> e.getServicerId()).collect(Collectors.toList());
				temp_servicerIds.removeAll(ruleServicerIds); //求差集，预先插入保存
				selectServicerId = temp_servicerIds.get(0);
				resultMap.put("code", "01");
				resultMap.put("servicerId", selectServicerId);
				return resultMap;
			}else{
				//到这里，说明规则中的服务商都已轮询下发过服务单，接下来根据权重去派发：ratioMap
				//ratioMap:系统配置占比；ruleCountMap:实际分发占比
				String newestServicerId = ""; //当前规则下，最近一次操作的服务商Id
				Date newestDate = null;
				int total = 0; //分发的总数，分母
				Map<String,String> ruleCountMap = new HashMap<>(); //key-value：规则统计中的数据：服务商Id-累计比
				for(int i=0; i<ruleCountList.size(); i++){
					RuleCountEntity entity = ruleCountList.get(i);
					total = entity.getCount();
					ruleCountMap.put(entity.getServicerId(), entity.getServerCount()*100/total+"");
					if(i==0){
						newestDate = entity.getCreateTime();
						newestServicerId = entity.getServicerId();
					}else{
						if(!newestDate.before(entity.getCreateTime())){
							newestDate = entity.getCreateTime();
							newestServicerId = entity.getServicerId();
						}
					}
				}
				//拿到最新操作的服务商Id,以它下一个服务商Id元素为起点，遍历规则，遍历完，都超过权重比，则取第一个服务商
				//'5,3,2,1'字符串，以动态值'3'为分隔，重新排序为2,1,5,3
				List<String> sortList = sortServicerId(servicerIds, newestServicerId);
				String resultServicerId = "";
				for(int i=0; i<sortList.size(); i++){
					String servicerId = sortList.get(i);
					String xtRatio = ratioMap.get(servicerId); //系统配置的权重比
					String sjRatio = ruleCountMap.get(servicerId); //实际分发占比
					int a_N = Integer.valueOf(xtRatio);
					int b_N = Integer.valueOf(sjRatio);
//					int result = xtRatio.compareTo(sjRatio); //1:大于；0:等于； -1:小于
					if(a_N > b_N){
						resultServicerId = servicerId;
						break;
					}
				}
				if(resultServicerId==""){ //表明实发占比不小于配置占比，默认取第一个服务商
					resultServicerId = servicerIds.get(0);
				}
				resultMap.put("code", "01");
				resultMap.put("servicerId", resultServicerId);
				return resultMap;
			}
		}
	}
	
	/**
	*
	* @author WANGCONG
	* 2021年10月18日下午6:47:52
	* @desc 根据服务商配置信息（服务类型、省市区）做匹配
	*/
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Map<String, String> matchServicer(Map<String, Object> paramsMap) {
		Map<String, String> resultMap = new HashMap<>();
        //查询满足的服务商列表信息
        List<ServiceProviderEntity> servicerList = providerService.choiceServicer(paramsMap);
        if(servicerList.size()==0){ //没有服务商匹配
        	resultMap.put("code", "03");
        	resultMap.put("msg", "没有匹配的服务商");
			return resultMap;
        }else if(servicerList.size()==1){ //只有一个服务商匹配
        	resultMap.put("code", "02");
        	resultMap.put("servicerId", servicerList.get(0).getId().toString());
        	Map<String,String> param = new HashMap<>();
			param.put("servicerId", servicerList.get(0).getId().toString());
			return resultMap;
        }else{ //存在多个，根据ServicerCountService接口(t_servicer_count)，轮询下发
        	List<Long> temp_List = servicerList.stream().map(ServiceProviderEntity::getId).collect(Collectors.toList());
        	List<String> providerIdList = temp_List.stream().map(String::valueOf).collect(Collectors.toList());
        	/**
        	 * 根据服务商id,查询当天的下发数量，按升序排列，如果满足的服务商个数和统计中的个数一致，说明都派发过，取最小派发量的服务商下发（列表第一个）；
        	 * 如果不相等，说明有服务商未派发过，随机取一个未派发过的服务商进行下发
        	 */
        	List<ServicerCountEntity> servicerCountList = servicerCountService.findCountByServicerList(providerIdList);
        	if(servicerList.size() == servicerCountList.size()){//说明这些服务商，今天都已轮询过，则取轮询数最小的服务商进行下发
        		ServicerCountEntity minVo = 
        				servicerCountList.stream().min(Comparator.comparing(ServicerCountEntity::getCount)).get();
        		resultMap.put("code", "02");
            	resultMap.put("servicerId", minVo.getServicerId());
            	return resultMap;
        	}else{//今天分发的还没有全轮询到，随机取一个未轮询到的服务商进行下发
                List<Long> l0 = servicerList.stream().map(ServiceProviderEntity::getId).collect(Collectors.toList());
                List<String> l1 = l0.stream().map(String::valueOf).collect(Collectors.toList());
                List<String> l2 = servicerCountList.stream().map(ServicerCountEntity::getDataId).collect(Collectors.toList());
                HashSet hs1 = new HashSet(l1);
                HashSet hs2 = new HashSet(l2);
                hs1.removeAll(hs2);
                
                List<Long> randomList = new ArrayList<Long>();
                randomList.addAll(hs1);
                Random random = new Random();
                String randomServicerId = String.valueOf(randomList.get(random.nextInt(randomList.size())));
                
                resultMap.put("code", "02");
            	resultMap.put("servicerId", randomServicerId);
            	return resultMap;
        	}
        	
        }
	}
	
	/**
	*
	* @author WANGCONG
	* 2021年10月18日下午4:36:28
	* @desc 服务商Id根据上次分发的Id重排序，eg：'5,3,2,1'字符串，以动态值'3'为分隔，重新排序为2,1,5,3
	*/
	public List<String> sortServicerId(List<String> servicerIds, String newestServicerId) {
		List<String> result = new ArrayList<>();
		if(newestServicerId.equals(servicerIds.get(0))){ //第一位
			for(int i=1; i<servicerIds.size(); i++){
				result.add(servicerIds.get(i));
			}
			result.add(newestServicerId);
		}else if(newestServicerId.equals(servicerIds.get(servicerIds.size()-1))){ //最后一位
			result = servicerIds;
		}else{ //中间位
			int index = servicerIds.indexOf(newestServicerId);
			for(int i=index+1; i<servicerIds.size(); i++){
				result.add(servicerIds.get(i));
			}
			for(int i=0; i<index; i++){
				result.add(servicerIds.get(i));
			}
			result.add(newestServicerId);
		}
		return result;
	}
	
	
}
